package com.etc.controller;

import com.etc.dto.Result;
import com.etc.entity.Department;
import com.etc.entity.Doctor;
import com.etc.entity.Time;
import com.etc.service.DepartmentService;
import com.etc.service.TimeService;
import com.etc.util.HisDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * author:qhy
 */
@Slf4j
@Controller
@RequestMapping("/time")
public class TimeController {
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private TimeService timeService;



    /**
     * 读取管理员上传的excel表格，录入到医生排班表中
     * @return
     */
    @PostMapping("/timeUpload")
    public @ResponseBody Result timeRead(@RequestParam(value = "file") MultipartFile file) throws IOException {
        Result result = new Result();



        //1.先上传到指定文件夹
        String fileName = file.getOriginalFilename();
        //2.存储文件


        File fileDestination = new File("D:\\upload\\excel");

        OutputStream out = new FileOutputStream(fileDestination+"\\"+fileName);
        out.write(file.getBytes());
        out.flush();
        out.close();

        //3.读取文件
        String excelPath = "D:\\upload\\excel"+"\\"+fileName;
        FileInputStream fis = new FileInputStream(excelPath);
        //创建工作簿
        Workbook workbook = new XSSFWorkbook(fis);
        //获取工作簿中的sheet数目
        int sheetNum = workbook.getNumberOfSheets();
        //由于格式统一，提取公共值：日期值
        Sheet sheetModel = workbook.getSheetAt(0);

        //获取单元格数
        int cells = sheetModel.getRow(0).getPhysicalNumberOfCells();
        //提取日期信息，将所有存入同一个hashMap中k：单元格 v：日期值
        HashMap<Integer,String> hashMap = new HashMap<>();
        for(int i=0;i<cells-2;i++){
            int k = sheetModel.getRow(0).getCell(i + 2).getColumnIndex();
            String v = sheetModel.getRow(0).getCell(i + 2).getStringCellValue();
            hashMap.put(k,v);
        }

        //定义无异常写入情况下所有值班数
        int resultNumTheory=0;
        //定义受影响行数
        int resultNum=0;

        //定义timeList
        List<Time> timeList = new ArrayList<>();
        //定义timeSet
        //Set<Time> timeSet = new TreeSet<>();


        //遍历各个sheet
        for(int i=0;i<sheetNum;i++){
            Sheet sheet = workbook.getSheetAt(i);
            //遍历rows，调用业务写入数据库
            //获取行数
            int rows = sheet.getPhysicalNumberOfRows();
            for(int j=1;j<rows;j++){
                //遍历单元格，判断值班、休息
                Row row = sheet.getRow(j);

                for(int k=2;k<cells;k++){
                    Cell cell = row.getCell(k);
                    String value = cell.getStringCellValue();
                    //若单元格值为值班，写入数据
                    if(value!=null && value.equals("值班")){
                        Time time = new Time();
                        time.setDoctorId(row.getCell(0).getStringCellValue());
                        time.setContent(hashMap.get(k));
                        //将排班对象time加入列表
                        timeList.add(time);
                        //将排班对象time加入set
                        //timeSet.add(time);
                        resultNumTheory++;
                    }

                }
            }

        }

        //写入数据库
        resultNum += timeService.addTime(timeList);

        //关闭流
        fis.close();


        //比较resultNum和resultNumTheory
        if (resultNumTheory>resultNum){
            result.fail(0,"写入异常！未写入全部数据，"+(resultNumTheory-resultNum)+"条数据插入失败！");
        }else {
            result.ok(true).setMessage("数据写入成功，共有"+resultNum+"条数据！sheetNum:"+sheetNum);
        }


        return result;
    }

    @GetMapping("/timeDemoDownload")
    public void timeDemoDownload(@RequestParam int year, @RequestParam int month, HttpServletResponse response) throws IOException {
        //创建工作簿
        Workbook workbook = new XSSFWorkbook();

        //获取所有科室
        List<Department> depts = departmentService.findAllDepartment();
        //遍历所有科室使之获取所在科室所有医生
        for(Department dept:depts){
            //根据部门名创建sheet表
            Sheet sheet = workbook.createSheet(dept.getDeptName());

            List<Doctor> doctors = departmentService.findAllDoctorByDeptId(dept.getDeptId());
            //dept.setDoctorList(doctors);
            //创建首行，设置首行内容
            Row row0 = sheet.createRow(0);
            //0,0
            row0.createCell(0).setCellValue("医生编号");
            row0.createCell(1).setCellValue("医生姓名/值班日期");
            //根据传入的year，month写入首行日期，利用工具获取该月份天数
            int days = HisDateUtil.maxDaysOfMonth(year, month);
            for(int i=0;i<days;i++){
                String str = new DateTime(year,month,i+1,0,0,0).toString("yyyy/MM/dd");
                row0.createCell(i+2).setCellValue(str);
            }

            //遍历医生列表，设置首列的内容（doctorId），次列的内容（doctorName）
            for(int i=0;i<doctors.size();i++){
                //获取列表中医生
                Doctor doctor = doctors.get(i);
                //创建每个医生的数据行
                Row row = sheet.createRow(i + 1);
                //设置首个单元格内容doctorId
                row.createCell(0).setCellValue(doctor.getDoctorId());
                //设置次单元格内容doctorName
                row.createCell(1).setCellValue(doctor.getDoctorName());
                //遍历天数，填充默认值
                for(int j=0;j<days;j++){
                    row.createCell(j+2).setCellValue("值班");
                }
            }
        }

        //设置响应头
        String fileName = year+"年"+month+"月医生排班表.xlsx";
        response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"utf-8"));
        //通过response获得servlet输出流将文件以字节形式输出到网页中
        ServletOutputStream sos = response.getOutputStream();
        //输出
        workbook.write(sos);
        //关闭流
        sos.close();
    }

    @GetMapping("/range")
    public @ResponseBody Result getDoctorTimeByIdAndRange(@RequestParam String doctorId,@RequestParam String date){
        Result result = new Result();
        List<Time> times = timeService.getDoctorTimeByRange(doctorId, date);
        if(!times.isEmpty()){
            result.ok(times);
        }else {
            result.fail(0,"未取得该医生排班信息");
        }


        return result;
    }

}
